import json
from openai import OpenAI
from config import Config
from typing import Dict, Optional


class AIService:
    """AI服务类，用于调用大模型生成总结"""
    
    def __init__(self):
        self.client = OpenAI(
            api_key=Config.OPENAI_API_KEY,
            base_url=Config.OPENAI_API_BASE,
            timeout=180.0  # 优化：减少到3分钟超时，提高响应速度
        )
        self.model = Config.OPENAI_MODEL
    
    def generate_summary(self, video_info: Dict, content: str) -> Dict:
        """生成视频总结"""
        try:
            # 构建提示词
            prompt = self._build_summary_prompt(video_info, content)
            
            # 调用大模型
            response = self.client.chat.completions.create(
                model=self.model,
                messages=[
                    {
                        "role": "system",
                        "content": "你是一个专业的视频内容分析助手，擅长总结视频内容并提取关键信息。"
                    },
                    {
                        "role": "user",
                        "content": prompt
                    }
                ],
                temperature=0.7,
                max_tokens=4000
            )
            
            # 处理不同API响应格式
            summary_text = self._extract_content(response)
            tokens_used = self._extract_tokens(response)
            
            return {
                'success': True,
                'data': {
                    'summary': summary_text,
                    'tokens_used': tokens_used
                }
            }
        except Exception as e:
            print(f"[错误] 生成总结失败: {str(e)}")
            print(f"[调试] 错误类型: {type(e).__name__}")
            import traceback
            traceback.print_exc()
            return {
                'success': False,
                'error': f'生成总结失败: {str(e)}'
            }
    
    def generate_mindmap(self, video_info: Dict, content: str, summary: Optional[str] = None) -> Dict:
        """生成思维导图（Markdown格式）"""
        try:
            prompt = self._build_mindmap_prompt(video_info, content, summary)
            
            response = self.client.chat.completions.create(
                model=self.model,
                messages=[
                    {
                        "role": "system",
                        "content": "你是一个专业的思维导图设计师，擅长将复杂内容结构化为清晰的思维导图。"
                    },
                    {
                        "role": "user",
                        "content": prompt
                    }
                ],
                temperature=0.7,
                max_tokens=2000
            )
            
            # 处理不同API响应格式
            mindmap_text = self._extract_content(response)
            tokens_used = self._extract_tokens(response)
            
            return {
                'success': True,
                'data': {
                    'mindmap': mindmap_text,
                    'tokens_used': tokens_used
                }
            }
        except Exception as e:
            print(f"[错误] 生成思维导图失败: {str(e)}")
            import traceback
            traceback.print_exc()
            return {
                'success': False,
                'error': f'生成思维导图失败: {str(e)}'
            }
    
    def generate_full_analysis(self, video_info: Dict, content: str, video_frames: Optional[list] = None, retry_count: int = 0) -> Dict:
        """生成完整分析（包括总结和思维导图）

        Args:
            video_info: 视频信息
            content: 文本内容（字幕/弹幕）
            video_frames: 可选的视频帧（base64编码列表）
        """
        try:
            print(f"[调试] 开始生成分析 - 模型: {self.model}")
            print(f"[调试] API Base: {Config.OPENAI_API_BASE}")
            print(f"[调试] 视频帧数量: {len(video_frames) if video_frames else 0}")

            # 构建综合提示词（支持弹幕内容）
            danmaku_preview = None
            if content and '【弹幕内容（部分）】' in content:
                # 提取弹幕预览用于分析
                danmaku_preview = content
            prompt = self._build_full_analysis_prompt(video_info, content, has_video_frames=bool(video_frames), danmaku_content=danmaku_preview)
            print(f"[调试] 提示词长度: {len(prompt)}")

            # 构建消息内容 - 适配新的多模态格式
            user_content = [
                {
                    "type": "text",
                    "text": prompt
                }
            ]

            # 添加视频帧（如果有的话）
            if video_frames and len(video_frames) > 0:
                for idx, frame_base64 in enumerate(video_frames):
                    user_content.append({
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{frame_base64}",
                            "detail": "low"  # 使用low detail以节省token
                        }
                    })
                    print(f"[调试] 添加第 {idx+1} 帧到消息中")

            # 使用新的消息格式调用API
            messages = [
                {
                    "role": "system",
                    "content": """你是一位资深的B站视频内容分析专家，擅长：
1. 深度内容解析 - 提取所有知识点、分析目的和含义
2. 结构化呈现 - 清晰的思维导图和层次结构
3. 互动数据分析 - 弹幕情感、热点、词云分析
4. 综合评价 - 多维度评分和学习建议

你能同时分析视频画面、文字内容和弹幕互动，提供全面、专业、易读的四大板块分析报告。
请严格按照要求的四大板块结构输出，内容详实、格式规范、逻辑清晰。"""
                },
                {
                    "role": "user",
                    "content": user_content
                }
            ]

            print(f"[调试] 发送请求到API...")
            response = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                temperature=0.6,  # 优化：降低温度，提高确定性和速度
                max_tokens=8000,  # 修复：增加token限制，避免内容截断
                timeout=240  # 修复：增加超时时间，确保完整响应
            )
            
            print(f"[调试] API响应类型: {type(response)}")
            print(f"[调试] API响应前100字符: {str(response)[:100]}")
            
            # 处理不同API响应格式
            analysis_text = self._extract_content(response)
            tokens_used = self._extract_tokens(response)
            
            # 尝试解析结构化内容
            parsed_content = self._parse_analysis_response(analysis_text)
            
            return {
                'success': True,
                'data': {
                    'full_analysis': analysis_text,
                    'parsed': parsed_content,
                    'tokens_used': tokens_used
                }
            }
        except Exception as e:
            print(f"[错误] 生成完整分析失败: {str(e)}")
            print(f"[调试] 错误类型: {type(e).__name__}")

            # 针对网络和超时错误的特殊处理
            if any(keyword in str(e).lower() for keyword in ['timeout', 'connection', 'network', '504', '502', '500']):
                if retry_count < 2:  # 最多重试2次
                    print(f"[重试] 检测到网络错误，正在进行第{retry_count + 1}次重试...")
                    print(f"[重试] 错误详情: {str(e)}")

                    if video_frames and len(video_frames) > 4:  # 如果帧数太多，减少到4帧
                        reduced_frames = video_frames[:4]
                        print(f"[降级] 减少视频帧数量: {len(video_frames)} → {len(reduced_frames)}")
                        return self.generate_full_analysis(video_info, content, reduced_frames, retry_count + 1)
                    elif video_frames and retry_count == 0:  # 第一次重试，去除视频帧
                        print(f"[降级] 放弃视频帧，仅使用文本分析")
                        return self.generate_full_analysis(video_info, content, None, retry_count + 1)

            import traceback
            traceback.print_exc()
            return {
                'success': False,
                'error': f'生成分析失败: {str(e)}'
            }
    
    def _build_summary_prompt(self, video_info: Dict, content: str) -> str:
        """构建总结提示词"""
        return f"""请为以下B站视频生成详细的总结报告：

【视频信息】
标题：{video_info.get('title', '未知')}
作者：{video_info.get('author', '未知')}
简介：{video_info.get('desc', '无')}

【视频内容】
{content[:Config.MAX_SUBTITLE_LENGTH]}

请提供以下内容：
1. **内容概述**（3-5句话概括视频主要内容）
2. **详细总结**（按逻辑结构详细总结视频内容，分段呈现）
3. **关键要点**（列出5-10个核心知识点）
4. **适用人群**（说明这个视频适合什么人观看）
5. **学习建议**（给出具体的学习建议）

请用清晰的Markdown格式输出，使用标题、列表等格式化元素。"""
    
    def _build_mindmap_prompt(self, video_info: Dict, content: str, summary: Optional[str]) -> str:
        """构建思维导图提示词"""
        base_content = f"""请为以下视频内容生成思维导图（使用Markdown格式）：

【视频标题】
{video_info.get('title', '未知')}

【视频内容】
{content[:Config.MAX_SUBTITLE_LENGTH]}
"""
        
        if summary:
            base_content += f"\n【已有总结】\n{summary}\n"
        
        base_content += """
请用Markdown格式的层级列表生成思维导图，结构清晰，层次分明。

格式示例：
# 视频标题
## 第一部分：核心概念
- 要点1
  - 子要点1.1
  - 子要点1.2
- 要点2
## 第二部分：具体内容
- 要点3
  - 子要点3.1

请确保：
1. 最多4层层级
2. 每个节点简洁明了
3. 逻辑结构清晰
4. 涵盖主要内容"""
        
        return base_content
    
    def _build_full_analysis_prompt(self, video_info: Dict, content: str, has_video_frames: bool = False, danmaku_content: str = None) -> str:
        """构建完整分析提示词（支持4大板块分析）"""
        video_analysis_hint = ""
        if has_video_frames:
            video_analysis_hint = """

**重要提示**：我还提供了视频的关键帧截图。请结合画面内容和文字内容进行全面分析，包括：
- 画面中的重要元素、场景、图表、代码等
- 视觉信息与文字内容的关联和互补
- PPT、演示文稿等视觉内容的详细解读
"""
        
        danmaku_hint = ""
        if danmaku_content:
            danmaku_hint = f"""

【弹幕内容预览】
{danmaku_content[:500]}...
（完整弹幕数据将在第三板块单独分析）
"""
        
        return f"""请对以下B站视频进行深度、全面的四大板块分析：

【视频基本信息】
标题：{video_info.get('title', '未知')}
UP主：{video_info.get('author', '未知')}
播放量：{video_info.get('view', 0):,}
点赞数：{video_info.get('like', 0):,}
视频简介：{video_info.get('desc', '无')}

【视频完整内容（字幕/文案）】
{content[:Config.MAX_SUBTITLE_LENGTH]}{video_analysis_hint}{danmaku_hint}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
请按照以下**四大板块**提供深度分析报告：
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

## 📋 第一板块：内容深度总结与分析

### 1. 视频概览（3-4句话）
- 核心主题和价值定位

### 2. 详细内容总结（分段详述）
**要求**：
- 按视频逻辑顺序，详细总结每个部分的内容
- 每段150-250字，涵盖所有提到的知识点
- 标注重要概念、术语、数据、案例
- 如有画面信息，描述关键视觉元素

### 3. 知识点详细解析
列出视频中提到的**所有知识点**，每个包含：
- **知识点名称**
- **定义/解释**：这是什么
- **重要性**：为什么重要
- **应用场景**：如何使用/何时用
- **相关概念**：与其他知识的关联

### 4. 目的与含义分析
- **作者意图**：UP主想表达什么？教学目标是什么？
- **深层含义**：内容背后的原理、思想、方法论
- **价值评估**：对观众的实际价值

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

## 🗺️ 第二板块：知识结构思维导图

**要求**：用清晰的Markdown层级列表呈现完整知识结构

```markdown
# {video_info.get('title', '视频标题')}

## 🎯 核心主题
- 主要论点1
  - 支撑论据1.1
  - 支撑论据1.2
    - 详细说明1.2.1
- 主要论点2

## 📚 知识体系
### 第一部分：[部分名称]
- 知识点A
  - 子知识点A1
  - 子知识点A2
- 知识点B

### 第二部分：[部分名称]
...

## 🔗 知识关联
- 前置知识 → 本视频内容 → 延伸学习

## 💡 关键启示
- 核心观点1
- 核心观点2
```

**格式规范**：
- 最多4层嵌套
- 每个节点简明扼要（10-20字）
- 逻辑清晰，结构完整
- 使用emoji增强可读性

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

## 💬 第三板块：弹幕互动分析

### 1. 弹幕情感基调
- 整体氛围：积极/中性/消极
- 观众态度：认同/质疑/讨论

### 2. 高频弹幕关键词（词云）
列出最常出现的15-20个关键词，按频率排序：
```
1. [关键词1] - 出现频率：高/中/低 - 含义解读
2. [关键词2] - ...
...
```

### 3. 弹幕洞察
- **热点时刻**：哪些片段弹幕最密集？为什么？
- **观众反馈**：
  - 👍 正面反馈（称赞、感谢、认同）
  - ❓ 疑问和困惑（观众不理解的地方）
  - 💡 观众补充（有价值的额外信息）
  - 🎭 梗/玩笑（娱乐性内容）
- **社区特色**：这个视频的弹幕文化特点

### 4. 弹幕价值提炼
- 观众最关心什么？
- 弹幕中有哪些有价值的讨论或补充？
- 反映出观众的知识水平和需求

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

## 🌟 第四板块：综合评价与建议

### 1. 内容质量评分（10分制）
- **信息密度**：[X/10] - 知识点的丰富程度
- **讲解清晰度**：[X/10] - 是否易于理解
- **实用性**：[X/10] - 实际应用价值
- **结构完整性**：[X/10] - 逻辑和组织
- **视觉呈现**：[X/10] - 画面质量（如有）
- **综合评分**：[X/10]

### 2. 适用人群
- **最适合**：[具体描述目标观众]
- **前置要求**：需要什么基础知识
- **不太适合**：哪些人可能不需要看

### 3. 学习路径建议
- **学前准备**：看这个视频前应该了解什么
- **学习重点**：观看时应着重关注的内容
- **延伸学习**：看完后可以学什么进阶内容
- **实践建议**：如何应用所学知识

### 4. 推荐与总结
- **一句话推荐**：[简洁有力的推荐语]
- **最大亮点**：这个视频最值得看的是什么
- **可改进之处**：（客观评价）

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

**输出要求**：
1. 使用清晰的Markdown格式，多用emoji和分隔线
2. 四大板块完整呈现，内容充实详细
3. 语言专业但易懂，适合快速阅读和深度学习
4. 如有视频帧，请详细描述画面中的关键信息
5. 总字数建议：2500-4000字"""
    
    def _extract_content(self, response) -> str:
        """提取响应内容，兼容不同API格式"""
        try:
            print(f"[调试] _extract_content - 响应类型: {type(response)}")
            
            # 尝试标准OpenAI格式
            if hasattr(response, 'choices') and response.choices:
                content = response.choices[0].message.content
                print(f"[调试] 提取到内容长度: {len(content) if content else 0}")
                
                # 检查是否是HTML（错误响应）
                if content and content.strip().startswith('<!doctype') or content.strip().startswith('<html'):
                    raise ValueError("API返回了HTML页面而不是文本内容，请检查API配置和网络连接")
                
                return content
            
            # 如果是字符串，直接返回
            if isinstance(response, str):
                # 检查是否是HTML
                if response.strip().startswith('<!doctype') or response.strip().startswith('<html'):
                    raise ValueError("API返回了HTML页面，请检查OPENAI_API_BASE配置")
                return response
            
            # 如果是字典，尝试提取内容
            if isinstance(response, dict):
                if 'choices' in response and response['choices']:
                    return response['choices'][0]['message']['content']
                if 'content' in response:
                    return response['content']
                if 'text' in response:
                    return response['text']
                # 如果字典中有error
                if 'error' in response:
                    raise ValueError(f"API返回错误: {response['error']}")
            
            # 尝试转换为字符串
            result = str(response)
            print(f"[警告] 响应格式未知，转为字符串: {result[:200]}")
            return result
        except Exception as e:
            print(f"[错误] 提取内容失败: {str(e)}, 响应类型: {type(response)}")
            raise
    
    def _extract_tokens(self, response) -> int:
        """提取token使用量，兼容不同API格式"""
        try:
            if hasattr(response, 'usage') and response.usage:
                if hasattr(response.usage, 'total_tokens'):
                    return response.usage.total_tokens
            
            if isinstance(response, dict):
                if 'usage' in response:
                    return response['usage'].get('total_tokens', 0)
            
            return 0
        except Exception as e:
            print(f"[警告] 提取tokens失败: {str(e)}")
            return 0
    
    def _parse_analysis_response(self, analysis_text: str) -> Dict:
        """解析分析响应，提取结构化内容"""
        sections = {
            'overview': '',
            'summary': '',
            'key_points': '',
            'mindmap': '',
            'audience': '',
            'suggestions': '',
            'rating': ''
        }
        
        # 简单的分段解析（可以根据实际需要优化）
        current_section = None
        lines = analysis_text.split('\n')
        
        for line in lines:
            line_lower = line.lower()
            if '概览' in line or 'overview' in line_lower:
                current_section = 'overview'
            elif '详细总结' in line or 'summary' in line_lower or '总结' in line:
                current_section = 'summary'
            elif '核心要点' in line or '要点' in line or 'key points' in line_lower:
                current_section = 'key_points'
            elif '思维导图' in line or 'mindmap' in line_lower:
                current_section = 'mindmap'
            elif '适用人群' in line or 'audience' in line_lower:
                current_section = 'audience'
            elif '学习建议' in line or 'suggestions' in line_lower or '建议' in line:
                current_section = 'suggestions'
            elif '推荐指数' in line or 'rating' in line_lower or '评分' in line:
                current_section = 'rating'
            elif current_section:
                sections[current_section] += line + '\n'
        
        return sections

